package org.duang.core;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Iterator;
import java.util.Map.Entry;

import org.apache.commons.lang3.StringUtils;
import org.duang.common.exceptios.ServiceException;
import org.duang.config.Config;
import org.duang.db.mongo.MongoDao;
import org.duang.db.sql.SqlDao;
import org.duang.ioc.Import;
import org.duang.kit.BeanKit;
import org.duang.kit.MongoKit;
import org.duang.kit.SqlKit;

public final class IocHepler {

	public static void init() {
		try {
			injectClass(); // 注入Service, Dao到Service层
		} catch (ServiceException se) {
			throw new ServiceException().setMessage(se.getMessage());
		} catch (Exception e) {
			throw new ServiceException(e.getMessage(), e);
		}
	}

	public static void injectService2Controller(Controller controller, Class<? extends Controller> controllerClass)
			throws Exception {
		Field[] fields = controllerClass.getDeclaredFields();
		for (int i = 0; i < fields.length; i++) {
			Field field = fields[i];
			if (null != field && field.isAnnotationPresent(Import.class)) {
				Object serviceObj = BeanKit.getBean(field.getType());
				if (null != serviceObj) {
					field.setAccessible(true);
					field.set(controller, serviceObj);
				}
			}
		}
	}

	private static void injectClass() throws ServiceException, Exception {
		String SERVICE_FLAG_NAME = StringUtils.split(Config.SERVICE_ENDWITH_NAME, ".")[0];
		String DAO_FLAG_NAME = StringUtils.split(Config.DAO_ENDWITH_NAME, ".")[0];
		for (Iterator<Entry<Class<?>, Object>> it = BeanKit.getBeanMap().entrySet().iterator(); it.hasNext();) {
			Entry<Class<?>, Object> entry = it.next();
			Object serviceObj = entry.getValue();
			Class<?> serviceClass = entry.getKey();
			Field[] fields = serviceClass.getDeclaredFields();
			for (int i = 0; i < fields.length; i++) {
				Field field = fields[i];
				if (null != field && field.isAnnotationPresent(Import.class)) {
					String fieldName = field.getName();
					if (fieldName.endsWith(SERVICE_FLAG_NAME)) {
						field.setAccessible(true);
						if (field.getType().equals(serviceClass)) {
							throw new ServiceException()
									.setMessage(serviceClass.getSimpleName() + " Can't Not Import From already!");
						}
						field.set(serviceObj, BeanKit.getBean(serviceObj, field.getType()));
					}
					if (fieldName.endsWith(DAO_FLAG_NAME)) {
						ParameterizedType paramType = (ParameterizedType) field.getGenericType();
						Type[] types = paramType.getActualTypeArguments();

						Class<?> paramTypeClazz = Class.forName(types[0].toString().substring(6).trim());
						Class<?> typeClazz = field.getType();
						Object daoObj = null;

						if (typeClazz.equals(MongoDao.class)) {
							daoObj = MongoKit.get(paramTypeClazz);
						}
						if (typeClazz.equals(SqlDao.class)) {
							daoObj = SqlKit.get(paramTypeClazz);
						}
						field.setAccessible(true);
						field.set(serviceObj, daoObj);
					}
				}
			}
		}
	}

}
